package triggerhelper.controllers;

import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import triggerhelper.*;
import triggerhelper.dataHolders.*;
import triggerhelper.helperClasses.*;
import triggerhelper.tabs.TriggerDataTab;

public class TriggerDataController {

    //instance variables
    private JButton bDelete, bHelp, bNewTrig, bSave, bSubmit, dialog_bOK, dialog_bCancel, dialog_bHelp;
    private JComboBox cbOptions;
    private JTextField fTrigName, dialog_fTrigName;
    private JList listTriggers;
    private JDialog dNewTrig;
    private JCheckBox dialog_cSimpleTrig;

    private TriggerDataTab theTab;
    private triggerCreator theParent;
    private SimpleTrigger currentTrigger;
    private DefaultListModel listModel;
    private JLabel mainTrigger, mainProject;

    private boolean componentsEnabled = false;

    //constructor
    public TriggerDataController(TriggerDataTab a, triggerCreator b) {
        theTab = a;
        theParent = b;
        setEasyAccessFields(a);
        listModel = (DefaultListModel)listTriggers.getModel();
        mainTrigger = b.getMainTrigger();
        mainProject = b.getMainProject();
        bNewTrig.requestFocusInWindow();
        setListeners();
    }

// <editor-fold defaultstate="collapsed" desc="EasyAccessFields and Listeners">
    private void setEasyAccessFields(TriggerDataTab a) {
        bDelete = a.getbDelete();
        bHelp = a.getbHelp();
        bNewTrig = a.getbNewTrig();
        bSave = a.getbSave();
        bSubmit = a.getbSubmit();
        cbOptions = a.getCbOptions();
        fTrigName = a.getfTrigName();
        listTriggers = a.getListTriggers();
        dNewTrig = a.getdNewTrig();
        dialog_fTrigName = a.getDialog_fTrigName();
        dialog_bOK = a.getDialog_bOk();
        dialog_bCancel = a.getDialog_bCancel();
        dialog_bHelp = a.getDialog_bHelp();
        dialog_cSimpleTrig = a.getDialog_cSimpleTrig();
    }

    private void setListeners() {
        fTrigName.addFocusListener(new java.awt.event.FocusAdapter() {

            @Override
            public void focusGained(java.awt.event.FocusEvent evt) {
                fTrigName.selectAll();
            }
        });
        fTrigName.addKeyListener(new java.awt.event.KeyAdapter() {

            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                    saveName();
                }
            }
        });
        bSave.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveName();
            }
        });
        listTriggers.addListSelectionListener(new javax.swing.event.ListSelectionListener() {

            @Override
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                updateCurrentTrigger();
            }
        });
        listTriggers.addKeyListener(new java.awt.event.KeyAdapter() {

            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
                    deleteTrigger();
                }
            }
        });
        listModel.addListDataListener(new javax.swing.event.ListDataListener() {

            @Override
            public void contentsChanged(ListDataEvent e) {}

            @Override
            public void intervalAdded(ListDataEvent e) {
                updateProject();
                if (!componentsEnabled) {
                    setComponents(true); //enable components
                }
            }

            @Override
            public void intervalRemoved(ListDataEvent e) {
                updateProject();
                if (listModel.isEmpty()) {
                    fTrigName.setText("<name>");
                    mainTrigger.setText("<trigger>");
                    currentTrigger = null;
                    theParent.setCurrentTrigger(null);
                    setComponents(false); //disable components
                    setTabs(false);
                }
            }

            private void updateProject() {
                TriggerProject tempP = theParent.getCurrentProject();
                if (tempP != null && tempP.isSaved()) {
                    tempP.setSaved(false);
                    mainProject.setText(tempP.getName() + "*");
                }
            }
        });
        bNewTrig.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                if (theParent.getCurrentProject() == null) {
                    JOptionPane.showMessageDialog(theParent, "You must create a project before creating a trigger");
                } else {
                    initNewTrigDialog();
                }
            }
        });
        bDelete.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteTrigger();
            }
        });
        bSubmit.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                submitOption();
            }
        });
        bHelp.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                help();
            }
        });

        dialog_bOK.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dialogOK();
            }
        });
        dialog_bCancel.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dialogCancel();
            }
        });
        dialog_bHelp.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dialogHelp();
            }
        });
        dialog_fTrigName.addFocusListener(new java.awt.event.FocusAdapter() {

            @Override
            public void focusGained(java.awt.event.FocusEvent evt) {
                dialog_fTrigName.selectAll();
            }
        });
        dialog_fTrigName.addKeyListener(new java.awt.event.KeyAdapter() {

            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                    dialogOK();
                }
            }
        });
        dialog_cSimpleTrig.addKeyListener(new java.awt.event.KeyAdapter() {

            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                    dialog_cSimpleTrig.setSelected(!dialog_cSimpleTrig.isSelected());
                }
            }
        });
    }// </editor-fold>

    public void addTrigger(SimpleTrigger t){
        // 1) add to list
        listModel.addElement(t);

        // 2) select trigger
        listTriggers.setSelectedValue(t, true);

        // 3) if simple -> create simple trigger window
        if(t.isSimple()){
            createSimpleWindow(true);
        }
    }

    public void saveName() {
        String triggerName = fTrigName.getText();
        if (isValid(triggerName)) {
            // change name
            JOptionPane.showMessageDialog(theParent, "-Name Saved-");
            currentTrigger.setName(triggerName);
            mainTrigger.setText(triggerName);
            listTriggers.requestFocusInWindow();
        } else {
            //reset name to original
            fTrigName.setText(currentTrigger.getName());
            fTrigName.selectAll();
            fTrigName.requestFocusInWindow();
        }
    }

    public void deleteTrigger() {
        if (listModel.isEmpty()) {
            return;
        }
        int option = JOptionPane.showConfirmDialog(theParent, "Are you sure you want to delete this trigger?");
        if (option == JOptionPane.YES_OPTION) {
            // 1) remove selected trigger
            int index = listTriggers.getSelectedIndex();
            listModel.remove(index); //calls the updateTrigger method

            // 2) find next available trigger
            if (index == listModel.size()) { //if deleted the last trigger, select previous trigger
                index--;
            }

            // 3) select trigger
            listTriggers.setSelectedIndex(index);
            listTriggers.ensureIndexIsVisible(index);
        }
    }

    // Called when changes are made to the JList (add/remove/select, etc)
    public void updateCurrentTrigger() {
//        if (listModel.isEmpty()) {
//            return;
//        }
        SimpleTrigger t = (SimpleTrigger)listTriggers.getSelectedValue();
        if (t != null) { //explicit filter for add/remove calls
            fTrigName.setText(t.getName());
            mainTrigger.setText(t.toString());
            currentTrigger = t;
            theParent.setCurrentTrigger(t);
            if (t.isSimple()) {
                setTabs(false); //disable tabs
            } else {
                setTabs(true); //enable tabs
            }
        }
    }

    private void submitOption(){
        int option = cbOptions.getSelectedIndex();
        switch(option){
            case 0:
                if(currentTrigger.isSimple()){
                    createSimpleWindow(false);
                }else{
                    TextFrame display = new TextFrame();
                    display.setTitle("Trigger Output");
                    display.setlMainTitle("Trigger Text");
                    display.setPreferredSize(new Dimension(462, 359));
                    int x = theParent.getX() + theParent.getWidth();
                    int y = theParent.getY();
                    display.setLocation(x, y);
                    display.setVisible(true);
                    TriggerCompiler.compileTrigger(display, currentTrigger);
                    display.gettOutput().setCaretPosition(0);
                }
                break;
            case 1:
                TriggerCompiler.compileProject(theParent, theParent.getCurrentProject());
                break;
        }
    }

    private void help() {
        //display help...
        throw new UnsupportedOperationException("Not yet implemented");
    }
    
    //Helper methods
    public boolean isValid(String name) {
        boolean isValid = true;
        if (name.isEmpty()) { //if textbox is empty
            JOptionPane.showMessageDialog(theParent, "Please enter a name");
            isValid = false;
        } else if (!InputErrorChecking.isAlphaNumeric(name) || !Character.isLetter(name.charAt(0))) {
            JOptionPane.showMessageDialog(theParent, "Please enter a valid name "
                    + "(name must be alpha-numeric and begin with a letter)");
            isValid = false;
        }
        for (int i=0; i<listModel.size() && isValid; i++) {
            SimpleTrigger t = (SimpleTrigger)listModel.get(i);
            if (t.getName().equals(name)) {
                JOptionPane.showMessageDialog(theParent, "This name already exists.  Please use different one.");
                isValid = false;
            }
        }
        return isValid;
    }
    private void setComponents(boolean b) {
        fTrigName.setEnabled(b);
        bSave.setEnabled(b);
        bDelete.setEnabled(b);
        cbOptions.setEnabled(b);
        bSubmit.setEnabled(b);
        theParent.getEmenuSave().setEnabled(b);
        theParent.getEmenuSaveAs().setEnabled(b);
        componentsEnabled = b;
    }
    private void setTabs(boolean b) {
        JTabbedPane pane = theParent.getMainTabPane();
        for (int i=1; i<pane.getTabCount(); i++) {
            pane.setEnabledAt(i, b);
        }
    }



    private void initNewTrigDialog() {
        dialog_fTrigName.setText("");
        dialog_cSimpleTrig.setSelected(false);
        dNewTrig.setLocationRelativeTo(theParent);
        dNewTrig.setVisible(true);
    }
    private void dialogOK() {
        dNewTrig.dispose();
        String triggerName = dialog_fTrigName.getText();

        //error checking
        if (isValid(triggerName)) {
            //new Trigger unless checkBox is checked
            if (dialog_cSimpleTrig.isSelected()) {
                addTrigger(new SimpleTrigger(triggerName)); //create new SimpleTrigger
            } else {
                addTrigger(new Trigger(triggerName)); //create new Trigger
            }
        } else {
            dialog_fTrigName.selectAll();
            dNewTrig.setVisible(true);
        }
    }
    private void dialogCancel() {
        dNewTrig.dispose();
    }
    private void dialogHelp() {
        //display help...
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private void createSimpleWindow(boolean firstTime){
        SimpleTriggerText a = new SimpleTriggerText();

        // 1) find location
        Toolkit toolkit = Toolkit.getDefaultToolkit ();
        Dimension d = toolkit.getScreenSize();
        int x = theParent.getX() + theParent.getWidth();
        int y = theParent.getY();

        // 2) reset location if off screen
        if (x + a.getWidth() > d.getWidth()) {
            x = (int)d.getWidth() - a.getWidth();
        }

        // 3) display window
        a.setLocation(x, y);
        a.setVisible(true);
        new SimpleTriggerController(a, theParent, firstTime);
    }
}
